import java.util.List;
import java.util.Iterator;
/**
 * Berekent de statistische aspecten van het programma
 * 
 * @author Eric de Potter
 * @version 9/5/2011
 */
public class Statistiek
{

    /**
     * Constructor for objects of class Statistiek
     */
    public Statistiek()
    {
    }
    
    /**
     * Berekent welke optredens de meeste likes hebben
     * 
     * @param  number  hoeveel elementen er in de top moeten zitten
     * @return     een array van optredens met de waarden geordend op de meeste likes 
     */
    public Optreden[] getMostLiked(int number)
    {
        List<Optreden> lijst_optredens = Database.getOptredens();
        Optreden[] optredens = toArray(lijst_optredens);
        //sorteert de lijst van optredens op aantal likes
        optredens = countingSort(optredens, "likes");
        //vult de top3 met de laatste n elemente (de grootste)
        Optreden[] mostLiked = select(optredens, number);
        
        return mostLiked;
    }
    
    /**
     * Berekent welke 3 optredens de meeste bezoekers hebben
     * 
     * @param  number  hoeveel elementen er in de top moeten zitten
     * @return     een array van optredens met de waarden geordend op de meeste bezoekers
     */
    public Optreden[] getMostAttended(int number)
    {
        List<Optreden> lijst_optredens = Database.getOptredens();
        Optreden[] optredens = toArray(lijst_optredens);
        //sorteert de lijst van optredens op aantal bezoekers
        optredens = countingSort(optredens, "attendants");
        //vult de top3 met de laatste n elementen (de grootste)
        Optreden[] mostAttended = select(optredens, number);
        
        return mostAttended;
    }
    
    /**
     * Berekent welke 3 optredens de meeste commentaren hebben
     * 
     * @param  number  hoeveel elementen er in de top moeten zitten
     * @return     een array van optredens met de waarden geordend op de meeste commentaren
     */
    public Optreden[] getMostComments(int number)
    {
        List<Optreden> lijst_optredens = Database.getOptredens();
        Optreden[] optredens = toArray(lijst_optredens);
        //sorteert de lijst van optredens op aantal bezoekers
        optredens = countingSort(optredens, "comments");
        //vult de top3 met de laatste 3 elemente (de grootste)
        Optreden[] mostComments = select(optredens, number);
        
        return mostComments;
    }
    
    /**
     * Selecteert het aantal optredens als is meegegeven als parameter
     * 
     * @param row  de rij vanwaar de elementen moeten geselecteerd worden
     * @param number  het aantal elemeten dat geselecteerd moet worden
     * @return  een array van de geselecteerde elementen
     */
    private Optreden[] select(Optreden[] row, int number)
    {
        Optreden[] selection;
        if (number < row.length)
            selection = new Optreden[number];
        else
            selection = new Optreden[row.length];
        for (int index = number; index > 0; index--) {
            if (index > row.length) {}
            else    
                selection[index-1] = row[row.length-index];
        }
        
        return selection;
    }
    
    /**
     * Zet de lijst van optredens om in een array van optredens
     * 
     * @param lijst  de lijst van optredens
     * @return  de overeenkomstige array
     */
    private Optreden[] toArray(List<Optreden> lijst)
    {
        Optreden[] optredens = new Optreden[lijst.size()];
        for (int index = 0; index < optredens.length; index++) {
            optredens[index] = lijst.get(index);
        }
        return optredens;
    }
    
    /**
     * Sorteert de rij van optredens met behulp van countingsort op basis van de meeste likes
     * 
     * @param  row de array die gesorteerd moet worden
     * @param  kind op wat de rij gesorteerd moet worden ("likes", "comments", "attendants")
     * @return  de gesorteerde rij
     */
    private Optreden[] countingSort(Optreden[] row, String kind)
    {
        int i;
        int max = getMax(row, kind) + 1;
        if (max != 0) {
            Optreden[] sorted = new Optreden[row.length];
            int[] places = new int[max];
            for (i=0; i<max; i++) {
                places[i] = 0;  //zet alle waarden op nul
            }
            for (i=0; i<row.length; i++) { //telt 1 bij in de array op positie van het aantal likes
                places[getInt(row[i], kind)]++;
            }
            for (i=1; i<max; i++) {
                places[i] = places[i] + places[i-1];
            }
            for (i=0; i<row.length; i++) {
                sorted[places[getInt(row[i], kind)]-1] = row[i];
                places[getInt(row[i], kind)]--;
            }
            return sorted;
        }
        else
            return row;
    }
    
    /**
     * Berekent het maximum van een array
     * 
     * @param row  de array waarvan het maximum berekent moet worden
     * @param kind  waarvan het maximum berekent moet worden ("likes", "comments", "attendants")
     * @return  het maximum
     */
    private int getMax(Optreden[] row, String kind)
    {
        int max = 0;
        int index = 0;
        while (index < row.length) {
            int number = getInt(row[index], kind);
            if (number > max)
                max = number;
            index++;
        }
        return max;
    }
    
    /**
     * Berekent bepaalde info van het optreden
     * 
     * @param optreden het optreden waarvan de info berekend moet worden
     * @param kind wat van het optreden berekend moet worden ("likes", "comments", "attendants")
     * @return het getal
     */
    private int getInt(Optreden optreden, String kind)
    {
        if (kind.equals("likes")) {
            return optreden.getLikes().size();
        }
        else if (kind.equals("attendants")) {
            return Database.getNumberAttendants(optreden);
        }
        else if (kind.equals("comments")) {
            return Database.getNumberComments(optreden);
        }
        //als hij hier geraakt klopt de meegegeven string niet
        return -1;
    }
}
